package org.springblade.modules.admin.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.DictCache;
import org.springblade.common.constant.BaseRoleConstant;
import org.springblade.common.utils.message.MessageCenterUtils;
import org.springblade.common.utils.message.domain.MessageParam;
import org.springblade.common.utils.message.domain.SendRequest;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.*;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.enums.*;
import org.springblade.modules.admin.mapper.MaintainAbarbeitungDetailMapper;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.*;
import org.springblade.modules.admin.vo.plan.PlanMaintainUserVO;
import org.springblade.modules.admin.vo.plan.PlanUserSignDetailVo;
import org.springblade.modules.notice.annotation.MsgNotice;
import org.springblade.modules.notice.core.event.NoticeEvent;
import org.springblade.modules.notice.dto.NoticeTaskParam;
import org.springblade.modules.notice.enums.BusinessType;
import org.springblade.modules.notice.enums.TriggerConditionEnum;
import org.springblade.modules.notice.enums.TriggerNodeEnum;
import org.springblade.modules.system.entity.TenantConfig;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.service.TenantConfigService;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@AllArgsConstructor
@Service
public class MaintainAbarbeitungServiceImpl extends BaseServiceImpl<MaintainAbarbeitungDetailMapper, MaintainAbarbeitungDetail> implements MaintainAbarbeitungService {

	private final IMaintainPlanContentService planContentService;
	private final IMaintainPlanContentExtService planContentExtService;
	private final IMaintainPlanContentUserService planContentUserService;
	private final MaintainPlanContentPersonnelService planContentPersonnelService;
	private final IMaintainByScoreQuestionService byScoreQuestionService;
	private final IMaintainSignService signService;
	private final MaintainMalfunctionLogService malfunctionLogService;
	private final MaintainAbarbeitungRecordService abarbeitungRecordService;
	private final IUserService userService;
	private final TenantConfigService tenantConfigService;
	private final ElevatorDeviceService elevatorDeviceService;
	private final MessageCenterUtils messageCenterUtils;
	private final ApplicationEventPublisher eventPublisher;
	private final Environment environment;
	private final ByScoreQuestionAppealService byScoreQuestionAppealService;

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Long submit(PlanAbarbeitungSaveDTO saveDTO) {

		if (Func.isEmpty(saveDTO.getByScoreQuestionIds())) {
			throw new ServiceException("工作项问题记录不可为空");
		}

		// 工单主表
		MaintainPlanContent planContent = new MaintainPlanContent();
		planContent.setElevatorId(saveDTO.getElevatorId());
		planContent.setPlanDate(saveDTO.getPlanDate());
		planContent.setPlanFinishDate(saveDTO.getFinishDate());
		planContent.setTypeStatus(MaintainPlanContentEnum.ABARBEITUNG.getId());
		if (Func.isNotEmpty(saveDTO.getUserIds())) {
			planContent.setStatus(TaskStatusEnum.ZG_TO_START.getStatus());
		} else {
			planContent.setStatus(TaskStatusEnum.ZG_ALLOCATION.getStatus());
		}
		planContentService.save(planContent);

		malfunctionLogService.insertWorkLog(planContent.getId(), "创建整改工单", TaskStatusEnum.ZG_ALLOCATION.getStatus());


		// 工单副表
		MaintainPlanContentExt planContentExt = new MaintainPlanContentExt();
		planContentExt.setPlanId(planContent.getId());
		planContentExt.setEmerProcType(saveDTO.getEmerProcType());
		planContentExt.setOverdueType(1);
		if (Func.isNotEmpty(planContent.getPlanFinishDate())) {
			long betweenDay = DateUtil.betweenDay(DateUtil.date(), planContent.getPlanFinishDate(), Boolean.TRUE);
			if (betweenDay <= 3) {
				planContentExt.setOverdueType(2);
			}
		}
		// 工单人员
		if (Func.isNotEmpty(saveDTO.getUserIds())) {
			List<MaintainPlanContentUser> planUsers = new ArrayList<>();
			saveDTO.getUserIds().forEach(e -> {
				MaintainPlanContentUser user = new MaintainPlanContentUser();
				user.setUserId(e);
				user.setPlanId(planContent.getId());
				planUsers.add(user);
			});
			planContentUserService.saveBatch(planUsers);
			// 冗余计划人员
			List<MaintainPlanContentPersonnel> planPersonnelList = new ArrayList<>();
			saveDTO.getUserIds().forEach(e -> {
				MaintainPlanContentPersonnel user = new MaintainPlanContentPersonnel();
				user.setUserId(e);
				user.setPlanId(planContent.getId());
				planPersonnelList.add(user);
			});
			planContentPersonnelService.saveBatch(planPersonnelList);

			planContentExt.setAllocateTime(DateUtil.date());
			planContentExt.setAllocateDuration(0L);
			List<User> users = userService.listByIds(saveDTO.getUserIds());
			malfunctionLogService.insertWorkLog(planContent.getId(), WorkTrackStatusEnum.ADD_USER.getTypeName() + "[" + StrUtil.join("/", users.stream().map(User::getRealName).collect(Collectors.toList())) + "]", planContent.getStatus());

			eventPublisher.publishEvent(new NoticeEvent(NoticeTaskParam.builder()
				.businessType(BusinessType.ABARBEITUNG.getCode())
				.triggerNode(TriggerNodeEnum.ASSIGN.getCode())
				.triggerCondition(TriggerConditionEnum.CONDITION_16.getCode())
				.bizId(planContent.getId())
				.tenantId(AuthUtil.getTenantId())
				.build()
			));
		}
		planContentExtService.save(planContentExt);

		// 工单详情表
		MaintainAbarbeitungDetail detail = new MaintainAbarbeitungDetail();
		detail.setPlanId(planContent.getId());
		detail.setCloseCount(0);
		detail.setReopenCount(0);
		detail.setRedeployCount(0);
		detail.setScoreIssue(saveDTO.getByScoreQuestionIds().size());
		super.save(detail);

		// 保养历史评分问题记录关联
		List<MaintainByScoreQuestion> byScoreQuestions = new ArrayList<>();
		saveDTO.getByScoreQuestionIds().forEach(e -> {
			MaintainByScoreQuestion byScoreQuestion = new MaintainByScoreQuestion();
			byScoreQuestion.setId(e);
			byScoreQuestion.setChildPlanType(planContent.getTypeStatus());
			byScoreQuestion.setChildPlanId(planContent.getId());
			byScoreQuestion.setChildPlanCreateUser(AuthUtil.getUserId());
			byScoreQuestion.setChildPlanCreateUserName(AuthUtil.getNickName());
			byScoreQuestions.add(byScoreQuestion);
		});
		byScoreQuestionService.updateBatchById(byScoreQuestions);

		//判断工单是否合规
		List<MaintainByScoreQuestion> maintainByScoreQuestions = byScoreQuestionService.list(Wrappers.<MaintainByScoreQuestion>lambdaQuery().eq(MaintainByScoreQuestion::getPlanId, saveDTO.getFromPlanId()));
		List<Integer> issueTypes = maintainByScoreQuestions.stream().filter(o -> o.getIssueType() != null).map(MaintainByScoreQuestion::getIssueType).distinct().collect(Collectors.toList());
		MaintainByScoreQuestionAppeal questionAppeal = byScoreQuestionAppealService.getOne(Wrappers.<MaintainByScoreQuestionAppeal>lambdaQuery().eq(MaintainByScoreQuestionAppeal::getPlanId, saveDTO.getFromPlanId()));
		if (issueTypes.contains(1)) {
			questionAppeal.setIsPass(0);
		} else {
			questionAppeal.setIsPass(1);
		}
		byScoreQuestionAppealService.updateById(questionAppeal);
		return planContent.getId();
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean addUser(PlanAbarbeitungSaveDTO saveDTO) {
		if (Func.isEmpty(saveDTO.getPlanId())) {
			throw new ServiceException("工单不可为空");
		}
		if (Func.isEmpty(saveDTO.getUserIds())) {
			throw new ServiceException("分配用户不可为空");
		}

		// 工单主表
		MaintainPlanContent planContent = planContentService.getById(saveDTO.getPlanId());
		planContent.setPlanDate(saveDTO.getPlanDate());
		planContent.setPlanFinishDate(saveDTO.getFinishDate());
		planContent.setStatus(TaskStatusEnum.ZG_TO_START.getStatus());
		planContentService.updateById(planContent);

		// 工单副表
		MaintainPlanContentExt planContentExt = planContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, saveDTO.getPlanId()));
		planContentExt.setOverdueType(1);
		if (Func.isNotEmpty(planContent.getPlanFinishDate())) {
			long betweenDay = DateUtil.betweenDay(DateUtil.date(), planContent.getPlanFinishDate(), Boolean.TRUE);
			if (betweenDay <= 3) {
				planContentExt.setOverdueType(2);
			}
		}
		// 工单人员
		if (Func.isNotEmpty(saveDTO.getUserIds())) {
			List<MaintainPlanContentUser> planUsers = new ArrayList<>();
			saveDTO.getUserIds().forEach(e -> {
				MaintainPlanContentUser user = new MaintainPlanContentUser();
				user.setUserId(e);
				user.setPlanId(planContent.getId());
				planUsers.add(user);
			});
			planContentUserService.saveBatch(planUsers);
			// 冗余计划人员
			List<MaintainPlanContentPersonnel> planPersonnelList = new ArrayList<>();
			saveDTO.getUserIds().forEach(e -> {
				MaintainPlanContentPersonnel user = new MaintainPlanContentPersonnel();
				user.setUserId(e);
				user.setPlanId(planContent.getId());
				planPersonnelList.add(user);
			});
			planContentPersonnelService.saveBatch(planPersonnelList);

			planContentExt.setAllocateTime(DateUtil.date());
			planContentExt.setAllocateDuration(0L);
			List<User> users = userService.listByIds(saveDTO.getUserIds());
			malfunctionLogService.insertWorkLog(planContent.getId(), WorkTrackStatusEnum.ADD_USER.getTypeName() + "[" + StrUtil.join("/", users.stream().map(User::getRealName).collect(Collectors.toList())) + "]", planContent.getStatus());

			eventPublisher.publishEvent(new NoticeEvent(NoticeTaskParam.builder()
				.businessType(BusinessType.ABARBEITUNG.getCode())
				.triggerNode(TriggerNodeEnum.ASSIGN.getCode())
				.triggerCondition(TriggerConditionEnum.CONDITION_16.getCode())
				.bizId(planContent.getId())
				.tenantId(AuthUtil.getTenantId())
				.build()
			));
		}
		planContentExtService.updateById(planContentExt);
		return planContentService.updateById(planContent);
	}

	@Override
	public String selectNextByDate(Long planId) {
		return planContentService.selectNextByDate(planId);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateZgPlanOverdueType(String tenantId) {

		List<PlanAbarbeitungPageVO> planContents = baseMapper.selectUnfinishPlanList(tenantId);
		if (Func.isNotEmpty(planContents)) {
			List<MaintainPlanContentExt> exts = new ArrayList<>();
			List<MaintainAbarbeitungDetail> details = new ArrayList<>();
			List<PlanAbarbeitungPageVO> redeployList = planContents.stream().filter(e -> e.getRedeployCount() > 0 && Func.isNotEmpty(e.getRedeployFinishDate())).collect(Collectors.toList());
			List<PlanAbarbeitungPageVO> notRedeployList = planContents.stream().filter(e -> e.getRedeployCount() <= 0 && Func.isNotEmpty(e.getPlanFinishDate())).collect(Collectors.toList());
			if (Func.isNotEmpty(redeployList)) {
				redeployList.forEach(e -> {
					MaintainAbarbeitungDetail detail = new MaintainAbarbeitungDetail();
					detail.setId(e.getDetailId());
					long betweenDay = DateUtil.betweenDay(DateUtil.date(), e.getRedeployFinishDate(), Boolean.TRUE);
					if (e.getRedeployFinishDate().getTime() >= DateUtil.parseDate(DateUtil.today()).getTime()) {
						if (betweenDay > 3) {
							detail.setRedeployOverdueStatus(1);
						} else {
							detail.setRedeployOverdueStatus(2);
						}
					} else {
						detail.setRedeployOverdueStatus(3);
					}
					details.add(detail);
				});
			}

			if (Func.isNotEmpty(notRedeployList)) {
				TenantConfig config = tenantConfigService.getTenantConfig(tenantId);
				ZgRedeployConfig zgRedeployConfig = config.getZgRedeployConfig();
				List<Long> allRedeployUserIds = new ArrayList<>();
				List<Long> redeployUserIds = new ArrayList<>();
				List<ElevatorDeptRoleUserDTO> eleDeptRoleUserList = new ArrayList<>();
				if (Func.isNotEmpty(zgRedeployConfig) && Func.isNotEmpty(zgRedeployConfig.getUserAndRoles())) {
					redeployUserIds = zgRedeployConfig.getUserAndRoles().stream().filter(e -> e.getType() == 1).map(ZgRedeployUserAndRole::getId).collect(Collectors.toList());
					if (Func.isNotEmpty(redeployUserIds)) {
						allRedeployUserIds.addAll(redeployUserIds);
					}
					List<Long> roleIds = zgRedeployConfig.getUserAndRoles().stream().filter(e -> e.getType() == 2).map(ZgRedeployUserAndRole::getId).collect(Collectors.toList());
					if (Func.isNotEmpty(roleIds)) {
						eleDeptRoleUserList = baseMapper.selectElevatorDeptRoleUser(roleIds, notRedeployList.stream().map(PlanAbarbeitungPageVO::getElevatorId).collect(Collectors.toList()));
						if (Func.isNotEmpty(eleDeptRoleUserList)) {
							allRedeployUserIds.addAll(eleDeptRoleUserList.stream().map(ElevatorDeptRoleUserDTO::getUserId).collect(Collectors.toList()));
						}
					}
				}
				List<User> redeployUsers = new ArrayList<>();
				if (Func.isNotEmpty(allRedeployUserIds)) {
					redeployUsers = userService.listByIds(allRedeployUserIds);
				}
				List<ElevatorDeptRoleUserDTO> needRedeployPlanIds = new ArrayList<>();

				List<Long> failPlanIds = new ArrayList<>();
				List<User> finalRedeployUsers = redeployUsers;
				List<Long> finalRedeployUserIds = redeployUserIds;
				List<ElevatorDeptRoleUserDTO> finalEleDeptRoleUserList = eleDeptRoleUserList;
				notRedeployList.forEach(e -> {
					MaintainPlanContentExt ext = new MaintainPlanContentExt();
					ext.setId(e.getExtId());
					if (e.getPlanFinishDate().getTime() > DateUtil.parseDate(DateUtil.today()).getTime()) {
						ext.setOverdueType(1);
					} else if (e.getPlanFinishDate().getTime() == DateUtil.parseDate(DateUtil.today()).getTime()) {
						ext.setOverdueType(2);
					} else {
						ext.setOverdueType(3);

						List<Long> finalUserIds = new ArrayList<>();
						finalUserIds.addAll(finalRedeployUserIds);
						finalUserIds.addAll(finalEleDeptRoleUserList.stream().filter(k -> k.getElevatorId().equals(e.getElevatorId())).map(ElevatorDeptRoleUserDTO::getUserId).collect(Collectors.toList()));
						// 逾期后自动转派
						if (Func.isNotEmpty(finalUserIds)) {
							List<User> users = finalRedeployUsers.stream().filter(u -> finalUserIds.contains(u.getId())).collect(Collectors.toList());
							ElevatorDeptRoleUserDTO v = new ElevatorDeptRoleUserDTO();
							v.setPlanId(e.getPlanId());
							v.setUserIds(users.stream().map(t -> String.valueOf(t.getId())).distinct().collect(Collectors.joining(",")));
							v.setUserNames(users.stream().map(t -> String.valueOf(t.getRealName())).distinct().collect(Collectors.joining(",")));
							needRedeployPlanIds.add(v);
							MaintainAbarbeitungDetail detail = new MaintainAbarbeitungDetail();
							detail.setId(e.getDetailId());
							detail.setRedeployCount(1);
							detail.setRedeployTime(DateUtil.date());
							detail.setRedeployUserIds(users.stream().map(t -> String.valueOf(t.getId())).distinct().collect(Collectors.joining(",")));
							detail.setRedeployUserNames(users.stream().map(t -> String.valueOf(t.getRealName())).distinct().collect(Collectors.joining(",")));
							detail.setRedeployOverdueStatus(1);
							if (Func.isNotEmpty(zgRedeployConfig.getRedeployDays())) {
								detail.setRedeployFinishDate(DateUtil.offsetDay(DateUtil.date(), zgRedeployConfig.getRedeployDays()));
								// 小于三天即将逾期
								if (zgRedeployConfig.getRedeployDays() <= 3) {
									detail.setRedeployOverdueStatus(2);
								}
							}
							details.add(detail);
						} else {
							failPlanIds.add(e.getPlanId());
						}

					}
					exts.add(ext);
				});

				if (Func.isNotEmpty(needRedeployPlanIds)) {

					// 处理未签退人员签退记录 统一系统代签
					List<MaintainSign> signList = signService.list(Wrappers.<MaintainSign>lambdaQuery()
						.in(MaintainSign::getPlanId, needRedeployPlanIds.stream().map(ElevatorDeptRoleUserDTO::getPlanId).collect(Collectors.toList()))
						.isNull(MaintainSign::getSignOutTime));
					if (Func.isNotEmpty(signList)) {
						signList.forEach(e -> {
							e.setSignOutTime(DateUtil.date());
							e.setSignOutStatus(1);
							e.setStatus(2);

							PlanAbarbeitungPageVO vo = planContents.stream().filter(t -> t.getPlanId().equals(e.getPlanId())).findFirst().orElse(new PlanAbarbeitungPageVO());
							PlanLogDTO planLogDTO = new PlanLogDTO();
							planLogDTO.setSignId(e.getId());
							planLogDTO.setExpDesc(WorkTrackStatusEnum.SYSTEM_SIGN.getTypeName());
							malfunctionLogService.insertWorkLog(e.getPlanId(), WorkTrackStatusEnum.SIGN_OUT.getTypeName(), vo.getPlanStatus(), JSONObject.toJSONString(planLogDTO), tenantId);
						});

						signService.updateBatchById(signList);
					}

					planContentUserService.remove(Wrappers.<MaintainPlanContentUser>lambdaQuery().in(MaintainPlanContentUser::getPlanId, needRedeployPlanIds.stream().map(ElevatorDeptRoleUserDTO::getPlanId).collect(Collectors.toList())));
					List<MaintainPlanContentUser> users = new ArrayList<>();
					needRedeployPlanIds.forEach(e -> {
						finalRedeployUsers.forEach(u -> {
							if (e.getUserIds().contains(String.valueOf(u.getId()))) {
								MaintainPlanContentUser user = new MaintainPlanContentUser();
								user.setPlanId(e.getPlanId());
								user.setUserId(u.getId());
								user.setTenantId(tenantId);
								users.add(user);
							}
						});

						PlanAbarbeitungPageVO vo = planContents.stream().filter(t -> t.getPlanId().equals(e.getPlanId())).findFirst().orElse(new PlanAbarbeitungPageVO());
						malfunctionLogService.insertWorkLog(vo.getPlanId(), "自动转派[" + e.getUserNames() + "]", vo.getPlanStatus(), null, tenantId);
					});
					List<List<MaintainPlanContentUser>> result = ListUtil.partition(users, 20);
					result.forEach(planContentUserService::saveBatch);

					needRedeployPlanIds.forEach(e -> {
						eventPublisher.publishEvent(new NoticeEvent(NoticeTaskParam.builder()
							.businessType(BusinessType.ABARBEITUNG.getCode())
							.triggerNode(TriggerNodeEnum.ASSIGN.getCode())
							.triggerCondition(TriggerConditionEnum.CONDITION_16.getCode())
							.bizId(e.getPlanId())
							.tenantId(tenantId)
							.build()
						));
					});

				}

				if (Func.isNotEmpty(failPlanIds)) {
					String curEnvironment = environment.getActiveProfiles()[0];
					List<User> userList = userService.getUserListOfRoleCode("workItemList", tenantId);
					if (Func.isNotEmpty(userList)) {
						String templateId;
						//当前环境
						if (Func.equalsSafe(curEnvironment, "prod")) {
							// 正式环境
							templateId = "1926807957384826881";
						} else {
							templateId = "1923273672197668866";
						}
						Map<String, String> contentMap = new HashMap<>(4);
						contentMap.put("title", "整改工单转派失败提醒");
						contentMap.put("content", String.format("累计有%s个整改工单自动转派失败，请及时跟进", failPlanIds.size()));
						contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, tenantId);
						SendRequest request = SendRequest.builder()
							.messageTemplateId(templateId)
							.messageParam(
								MessageParam.builder()
									.receiver(userList.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(",")))
									.variables(contentMap)
									.build()
							).build();
						R r = messageCenterUtils.sendMessage(request);
						log.info("梯无忧PC推送结果:" + JSON.toJSONString(r));
					}
				}

			}

			if (Func.isNotEmpty(exts)) {
				List<List<MaintainPlanContentExt>> result = ListUtil.partition(exts, 20);
				result.forEach(planContentExtService::updateBatchById);
			}
			if (Func.isNotEmpty(details)) {
				List<List<MaintainAbarbeitungDetail>> result = ListUtil.partition(details, 20);
				result.forEach(super::updateBatchById);
			}
		}

	}

	@Override
	public IPage<PlanAbarbeitungPageVO> selectPage(PlanAbarbeitungSearchDTO searchDTO, IPage<PlanAbarbeitungPageVO> page) {
		return page.setRecords(baseMapper.selectPlanAbarbeitungPage(searchDTO, page));
	}

	@Override
	public List<PlanAbarbeitungPageVO> downList(PlanAbarbeitungSearchDTO searchDTO) {
		return baseMapper.selectPlanAbarbeitungPage(searchDTO, null);
	}

	@Override
	public Map<String, Object> selectPageCount() {
		return baseMapper.selectPageCount();
	}

	@Override
	public PlanAbarbeitungDetailVO selectDetail(Long planId) {
		PlanAbarbeitungDetailVO detailVO = baseMapper.selectDetail(planId);
		if (Func.isEmpty(detailVO)) {
			throw new ServiceException("该整改工单不存在");
		}

		// 查询来源工单历史记录
		List<PlanAbarbeitungByContentVO> fromHistoryList = baseMapper.selectFromHistoryList(planId);
		detailVO.setFromHistoryList(fromHistoryList);

		List<PlanAbarbeitungByContentVO> afterHistoryList;
		if (detailVO.getPlanStatus().equals(TaskStatusEnum.ZG_ALLOCATION.getStatus()) || detailVO.getPlanStatus().equals(TaskStatusEnum.ZG_TO_START.getStatus())) {
			afterHistoryList = baseMapper.selectAfterHistoryListByTemplateContent(planId);
		} else {
			afterHistoryList = baseMapper.selectAfterHistoryListByCheckHistory(planId);
		}
		detailVO.setAfterHistoryList(afterHistoryList);

		// 人员信息
		List<PlanMaintainUserVO> maintainUserList = planContentUserService.selectWorkUsers(planId);
		detailVO.setMaintainUserList(maintainUserList);

		WorkTrackVO workTrack = malfunctionLogService.selectWorkTracks(planId);
		detailVO.setWorkTrack(workTrack);
		return detailVO;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean close(MaintainAbarbeitungRecord record) {
		MaintainPlanContent planContent = planContentService.getById(record.getPlanId());
		if (Func.isEmpty(planContent)) {
			throw new ServiceException("该整改工单不存在");
		}
		if (planContent.getStatus().equals(TaskStatusEnum.ZG_CLOSED.getStatus())) {
			throw new ServiceException("工单状态已变更，请刷新页面");
		}

		// 处理未签退人员签退记录 统一系统代签
		List<MaintainSign> signList = signService.list(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, record.getPlanId()).isNull(MaintainSign::getSignOutTime));
		if (Func.isNotEmpty(signList)) {
			signList.forEach(e -> {
				e.setSignOutTime(DateUtil.date());
				e.setSignOutStatus(1);
				e.setStatus(2);

				User user = userService.getById(e.getUserId());
				PlanLogDTO planLogDTO = new PlanLogDTO();
				planLogDTO.setSignId(e.getId());
				planLogDTO.setExpDesc(WorkTrackStatusEnum.SYSTEM_SIGN.getTypeName());
				malfunctionLogService.insertWorkLog(e.getPlanId(), WorkTrackStatusEnum.SIGN_OUT.getTypeName(), planContent.getStatus(), JSONObject.toJSONString(planLogDTO), AuthUtil.getUserId(), user.getRealName());
			});

			signService.updateBatchById(signList);
		}

		abarbeitungRecordService.save(record);
		MaintainAbarbeitungDetail detail = super.getOne(Wrappers.<MaintainAbarbeitungDetail>lambdaQuery().eq(MaintainAbarbeitungDetail::getPlanId, record.getPlanId()));
		detail.setCloseCount(detail.getCloseCount() + 1);
		detail.setCloseTime(DateUtil.date());

		planContent.setStatus(TaskStatusEnum.ZG_CLOSED.getStatus());

		//关闭工单需要把所有的人工单头像亮--to--不亮
		List<MaintainPlanContentUser> planContentUserList = planContentUserService.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, record.getPlanId()));
		for (MaintainPlanContentUser maintainPlanContentUser : planContentUserList) {
			PlanUserSignDetailVo signUser = maintainPlanContentUser.getSignUser();
			if (signUser != null) {
				signUser.setIsPlanStatus(false);
			}
			maintainPlanContentUser.setSignInfo(JSONObject.toJSONString(signUser));
		}
		//处理逾期状态
		MaintainPlanContentExt ext = planContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, record.getPlanId()));
		if (detail.getRedeployCount() > 0) {
			detail.setRedeployOverdueStatus(1);
			if (Func.isNotEmpty(detail.getRedeployFinishDate())) {
				if (detail.getRedeployFinishDate().getTime() < DateUtil.parseDate(DateUtil.today()).getTime()) {
					detail.setRedeployOverdueStatus(3);
				}
			}
		} else {
			ext.setOverdueType(1);
			if (Func.isNotEmpty(planContent.getPlanFinishDate())) {
				if (planContent.getPlanFinishDate().getTime() < DateUtil.parseDate(DateUtil.today()).getTime()) {
					ext.setOverdueType(3);
				}
			}
		}
		this.updateById(detail);

		planContentExtService.updateById(ext);
		planContentUserService.updateBatchById(planContentUserList);
		malfunctionLogService.insertWorkLog(planContent.getId(), "关闭整改工单", planContent.getStatus());
		return planContentService.updateById(planContent);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean redeploy(MaintainAbarbeitungRecord record) {
		MaintainPlanContent planContent = planContentService.getById(record.getPlanId());
		if (Func.isEmpty(planContent)) {
			throw new ServiceException("该整改工单不存在");
		}
		if (planContent.getStatus().equals(TaskStatusEnum.ZG_CLOSED.getStatus())) {
			throw new ServiceException("工单已关闭");
		}
		if (planContent.getStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())) {
			throw new ServiceException("工单已完成");
		}

		MaintainPlanContentExt planContentExt = planContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, record.getPlanId()));
		planContentExt.setOverdueType(1);
		if (Func.isNotEmpty(planContent.getPlanFinishDate()) && planContent.getPlanFinishDate().getTime() < DateUtil.parseDate(DateUtil.today()).getTime()) {
			planContentExt.setOverdueType(3);
		}
		MaintainAbarbeitungDetail detail = super.getOne(Wrappers.<MaintainAbarbeitungDetail>lambdaQuery().eq(MaintainAbarbeitungDetail::getPlanId, record.getPlanId()));
		TenantConfig tenantConfig = tenantConfigService.getTenantConfig(AuthUtil.getTenantId());
		detail.setRedeployCount(detail.getRedeployCount() + 1);
		detail.setRedeployTime(DateUtil.date());
		detail.setRedeployUserIds(record.getRedeployUserIds());
		detail.setRedeployUserNames(record.getRedeployUserNames());
		detail.setRedeployFinishDate(DateUtil.offsetDay(DateUtil.date(), tenantConfig.getZgRedeployConfig().getRedeployDays()));
		detail.setRedeployOverdueStatus(1);
		// 小于三天即将逾期
		if (tenantConfig.getZgRedeployConfig().getRedeployDays() <= 3) {
			detail.setRedeployOverdueStatus(2);
		}
		super.updateById(detail);

		// 处理未签退人员签退记录 统一系统代签
		List<MaintainSign> signList = signService.list(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, record.getPlanId()).isNull(MaintainSign::getSignOutTime));
		if (Func.isNotEmpty(signList)) {
			signList.forEach(e -> {
				e.setSignOutTime(DateUtil.date());
				e.setSignOutStatus(1);
				e.setStatus(2);

				User user = userService.getById(e.getUserId());
				PlanLogDTO planLogDTO = new PlanLogDTO();
				planLogDTO.setSignId(e.getId());
				planLogDTO.setExpDesc(WorkTrackStatusEnum.SYSTEM_SIGN.getTypeName());
				malfunctionLogService.insertWorkLog(e.getPlanId(), WorkTrackStatusEnum.SIGN_OUT.getTypeName(), planContent.getStatus(), JSONObject.toJSONString(planLogDTO), AuthUtil.getUserId(), user.getRealName());
				planContentUserService.updatePlanUserSignInfo(e.getPlanId(), SignEnum.SIGN_OUT.getId(), AuthUtil.getUserId(), e.getSignOutStatus());
			});

			signService.updateBatchById(signList);
		}

		planContentUserService.remove(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, record.getPlanId()));
		List<MaintainPlanContentUser> redeployUsers = new ArrayList<>();
		Func.toStrList(record.getRedeployUserIds()).forEach(e -> {
			MaintainPlanContentUser planContentUser = new MaintainPlanContentUser();
			planContentUser.setUserId(Long.valueOf(e));
			planContentUser.setPlanId(record.getPlanId());
			redeployUsers.add(planContentUser);
		});

		List<User> users = userService.listByIds(Func.toLongList(record.getRedeployUserIds()));
		malfunctionLogService.insertWorkLog(planContent.getId(), WorkTrackStatusEnum.REDEPLOY_USER.getTypeName() + "[" + StrUtil.join("/", users.stream().map(User::getRealName).collect(Collectors.toList())) + "]", planContent.getStatus());


		abarbeitungRecordService.save(record);
		planContentUserService.saveBatch(redeployUsers);

		eventPublisher.publishEvent(new NoticeEvent(NoticeTaskParam.builder()
			.businessType(BusinessType.ABARBEITUNG.getCode())
			.triggerNode(TriggerNodeEnum.ASSIGN.getCode())
			.triggerCondition(TriggerConditionEnum.CONDITION_16.getCode())
			.bizId(record.getPlanId())
			.tenantId(AuthUtil.getTenantId())
			.build()
		));
		return planContentExtService.updateById(planContentExt);
	}

	@MsgNotice(businessType = BusinessType.ABARBEITUNG, node = TriggerNodeEnum.REOPEN, parameterName = "record.planId")
	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean reopen(MaintainAbarbeitungRecord record) {
		MaintainPlanContent planContent = planContentService.getById(record.getPlanId());
		if (Func.isEmpty(planContent)) {
			throw new ServiceException("该整改工单不存在");
		}
		MaintainPlanContentExt planContentExt = planContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, record.getPlanId()));
		MaintainAbarbeitungDetail detail = super.getOne(Wrappers.<MaintainAbarbeitungDetail>lambdaQuery().eq(MaintainAbarbeitungDetail::getPlanId, record.getPlanId()));

		// 重新打开工单时 有过转派更新转派截止时间 否则更新计划截止时间
		if (detail.getRedeployCount() > 0) {
			detail.setRedeployFinishDate(record.getFinishDate());
			detail.setRedeployOverdueStatus(1);
			long betweenDay = DateUtil.betweenDay(DateUtil.date(), record.getFinishDate(), Boolean.TRUE);
			if (betweenDay <= 3) {
				detail.setRedeployOverdueStatus(2);
			}
		} else {
			planContent.setPlanFinishDate(record.getFinishDate());
			planContentExt.setOverdueType(1);
			long betweenDay = DateUtil.betweenDay(DateUtil.date(), record.getFinishDate(), Boolean.TRUE);
			if (betweenDay <= 3) {
				planContentExt.setOverdueType(2);
			}
		}

		detail.setReopenCount(detail.getReopenCount() + 1);
		detail.setReopenTime(DateUtil.date());
		super.updateById(detail);

		planContentExt.setPlanEndTime(null);
		planContentExtService.updateById(planContentExt);
		abarbeitungRecordService.save(record);
		malfunctionLogService.insertWorkLog(record.getPlanId(), "重新打开任务", planContent.getStatus());

		long planUserCount = planContentUserService.count(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, record.getPlanId()));
		long planUserSignCount = signService.count(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, record.getPlanId()));
		if (planUserCount <= 0) {
			planContent.setStatus(TaskStatusEnum.ZG_ALLOCATION.getStatus());
		} else {
			if (planUserSignCount > 0) {
				planContent.setStatus(TaskStatusEnum.ZG_UNDER_WAY.getStatus());
			} else {
				planContent.setStatus(TaskStatusEnum.ZG_TO_START.getStatus());
			}
		}
		return planContentService.updateById(planContent);
	}

	@Override
	public List<MaintainAbarbeitungRecord> recordList(Long planId) {
		return abarbeitungRecordService.recordList(planId);
	}

	@Override
	public List<FromPlanVO> fromPlan(Long planId) {
		List<FromPlanVO> resultList = new ArrayList<>();
		List<MaintainByScoreQuestion> byScoreQuestions = byScoreQuestionService.list(Wrappers.<MaintainByScoreQuestion>lambdaQuery().eq(MaintainByScoreQuestion::getChildPlanId, planId));
		if (Func.isNotEmpty(byScoreQuestions)) {
			List<Long> fromPlanIds = byScoreQuestions.stream().map(MaintainByScoreQuestion::getPlanId).distinct().collect(Collectors.toList());
			if (fromPlanIds.size() > 0) {
				resultList = baseMapper.selectZgFromPlan(fromPlanIds);
				if (Func.isNotEmpty(resultList)) {
					resultList.forEach(e -> {
						e.setPlanTypeStatusName(MaintainPlanContentEnum.getName(e.getPlanTypeStatus()));
						e.setPlanStatusName(TaskStatusEnum.getTaskName(e.getPlanTypeStatus(), e.getPlanStatus()));
					});
				}
			}

		}
		return resultList;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean updateDate(AbarbeitungPlanDateUpdateDTO dateUpdateDTO) {
		MaintainPlanContent planContent = planContentService.getById(dateUpdateDTO.getPlanId());
		if (Func.isEmpty(planContent)) {
			throw new ServiceException("该整改工单不存在");
		}
		if (planContent.getStatus().equals(TaskStatusEnum.ZG_CLOSED.getStatus())) {
			throw new ServiceException("工单已关闭");
		}
		if (planContent.getStatus().equals(TaskStatusEnum.ZG_SIGN_FINISH.getStatus())) {
			throw new ServiceException("工单已完成");
		}


		if (dateUpdateDTO.getTemp().equals(3)) {
			MaintainAbarbeitungDetail detail = super.getOne(Wrappers.<MaintainAbarbeitungDetail>lambdaQuery().eq(MaintainAbarbeitungDetail::getPlanId, dateUpdateDTO.getPlanId()));
			detail.setRedeployFinishDate(dateUpdateDTO.getUpdateDate());
			detail.setRedeployOverdueStatus(1);
			long betweenDay = DateUtil.betweenDay(DateUtil.date(), dateUpdateDTO.getUpdateDate(), Boolean.TRUE);
			if (betweenDay <= 3) {
				detail.setRedeployOverdueStatus(2);
			}
			return super.updateById(detail);
		} else if (dateUpdateDTO.getTemp().equals(2)) {
			MaintainPlanContentExt planContentExt = planContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, dateUpdateDTO.getPlanId()));
			planContent.setPlanFinishDate(dateUpdateDTO.getUpdateDate());
			planContentExt.setOverdueType(1);
			long betweenDay = DateUtil.betweenDay(DateUtil.date(), dateUpdateDTO.getUpdateDate(), Boolean.TRUE);
			if (betweenDay <= 3) {
				planContentExt.setOverdueType(2);
			}
			planContentService.updateById(planContent);
			return planContentExtService.updateById(planContentExt);
		} else {
			planContent.setPlanDate(dateUpdateDTO.getUpdateDate());
			return planContentService.updateById(planContent);
		}
	}

}
